#pragma once

#include "zrpc/base/thread_pool.h"
#include "zrpc/net/acceptor.h"
#include "zrpc/net/callback.h"

namespace zrpc {
class EventLoop;

class TcpServer {
 public:
  typedef std::function<void(EventLoop *)> ThreadInitCallback;

  TcpServer(EventLoop *loop, const std::string &ip, int16_t port,
            const std::any &context);

  ~TcpServer();

  void NewConnection(int32_t sockfd);

  void Start();

  void RemoveConnection(const std::shared_ptr<TcpConnection> &conn);

  void RemoveConnectionInLoop(const std::shared_ptr<TcpConnection> &conn);


  void SetAcceptCallback(const AcceptCallback &&cb) {
    accept_callback_ = std::move(cb);
  }

  void SetThreadInitCallback(const ThreadInitCallback &&cb) {
    thread_init_callback_ = std::move(cb);
  }

  void SetConnectionCallback(const ConnectionCallback &&cb) {
    connection_callback_ = std::move(cb);
  }

  void SetMessageCallback(const MessageCallback &&cb) {
    message_callback_ = std::move(cb);
  }

  // void SetMessage1Callback(const Message1Callback &&cb) {
  //  message1_callback_ = std::move(cb);
  //}

  void SetWriteCompleteCallback(const WriteCompleteCallback &&cb) {
    write_complete_callback_ = std::move(cb);
  }

  void SetThreadNum(int16_t num_threads);

  EventLoop *GetLoop() const { return loop_; }

  std::shared_ptr<ThreadPool> GetThreadPool() { return thread_pool_; }

  std::any *GetMutableContext() { return &context_; }

  const std::any &GetContext() const { return context_; }

  void SetContext(const std::any &context) { context_ = context; }

 private:
  TcpServer(const TcpServer &);

  void operator=(const TcpServer &);

  EventLoop *loop_;
  std::unique_ptr<Acceptor> acceptor_;
  std::shared_ptr<ThreadPool> thread_pool_;
  AcceptCallback accept_callback_;
  ConnectionCallback connection_callback_;
  MessageCallback message_callback_;
  //Message1Callback message1_callback_;
  WriteCompleteCallback write_complete_callback_;
  ThreadInitCallback thread_init_callback_;

  typedef std::unordered_map<int32_t, std::shared_ptr<TcpConnection>>
      ConnectionMap;
  ConnectionMap connections_;
  std::any context_;
};
}  // namespace zrpc
